package com.epam.Bank;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.log4j.Logger;

public class Bank {

	public enum Currency {
		USD, Euro
	}

	private static Map<Integer, Account> accountMap = new ConcurrentHashMap<Integer, Account>();
	private static List<Integer> accounts = new ArrayList<Integer>();
	private static final Logger log = Logger.getLogger(Bank.class);
	private static BlockingQueue<Cashier> cashiers = new LinkedBlockingQueue<Cashier>(
			3);
	private static BlockingQueue<Observer> observers = new LinkedBlockingQueue<Observer>(
			1);

	private static Properties prop = new Properties();

	private static int storageUSD;
	private static int storageEuro;
	private static double EuroToUSDRate;
	private static double USDToEuroRate;

	/**
	 * @return true if account exists;
	 */

	public static boolean checkAccountNumbers(int accountNumber) {
		boolean a = Bank.getAccountMap().containsKey(accountNumber);
		return a;
	}

	public static synchronized void collectMoney(Cashier c) {
		int i = c.getCashierCashEuro() - 100;
		int j = c.getCashierCashUSD() - 100;
		c.setCashierCashUSD(100);
		c.setCashierCashEuro(100);
		Bank.setStorageEuro(Bank.getStorageEuro() + i);
		Bank.setStorageUSD(Bank.getStorageUSD() + j);
		log.info("Money moved to storage");
	}

	public static boolean checkCashOverflow(Cashier c) {
		if (c.getCashierCashEuro() > 200 || c.getCashierCashUSD() > 200) {
			return true;
		}
		return false;
	}

	public static synchronized Cashier getCashier() {
		try {
			return cashiers.take();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	public static double getEuroToUSDRate() {
		return EuroToUSDRate;
	}

	public static int getStorageEuro() {
		return storageEuro;
	}

	public static int getStorageUSD() {
		return storageUSD;
	}

	public static double getUSDToEuroRate() {
		return USDToEuroRate;
	}

	public static void rateInitialization() throws FileNotFoundException,
			IOException {
		prop.load(new FileReader("src/main/resources/rates.properties"));
		setStorageEuro(Integer.parseInt((prop.getProperty("storageEuro"))));
		setStorageUSD(Integer.parseInt((prop.getProperty("storageUSD"))));
		setEuroToUSDRate(Double
				.parseDouble((prop.getProperty("EuroToUSDRate"))));
		setUSDToEuroRate(Double
				.parseDouble((prop.getProperty("USDToEuroRate"))));
	}

	public static void setAccounts(int accountNumber) {
		Bank.accounts.add(accountNumber);
	}

	public static void setCashier(Cashier c) {
		try {
			Bank.cashiers.put(c);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static Queue<Cashier> getCashiers() {
		return cashiers;
	}

	public static void setEuroToUSDRate(double euroToUSDRate) {
		EuroToUSDRate = euroToUSDRate;
	}

	public static void setStorageEuro(int storageEuro) {
		Bank.storageEuro = storageEuro;
	}

	public static void setStorageUSD(int storageUSD) {
		Bank.storageUSD = storageUSD;
	}

	public static void setUSDToEuroRate(double uSDToEuroRate) {
		USDToEuroRate = uSDToEuroRate;
	}

	public static Map<Integer, Account> getAccountMap() {
		return accountMap;
	}

	public static synchronized void setAccountMap(Account account) {
		Bank.accountMap.put(account.getAccountNumber(), account);
	}

	public static Observer getObservers() {
		try {
			return observers.take();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void setObservers(Observer observer) {
		try {
			Bank.observers.put(observer);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}
